package bt.basics.common.utils;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.util.*;

/**
 * Xml工具类
 */
public class XmlUtils {

    private static XmlMapper xmlMapper = new XmlMapper();

    public static Object getLinkedHashMapToBean(Object map, Class<?> cl) {
        return xmlMapper.convertValue(map, cl);
    }

    public static <T> List<T>  getArrayListLinkedHashMapToListBean(List<T> list,Class<?> cl){
        if(list == null || list.size()<1){
            return null;
        }
        List<T> ResList = new ArrayList<T>();
        for (T obj:list){
            ResList.add((T)xmlMapper.convertValue(obj, cl));
        }
        return ResList;
    }

    /**
     * @param obj      需要转换为xml的实体
     * @param encoding 编码
     * @return
     * @throws JAXBException
     */
    public static String getXmlStr(Object obj, String encoding) throws JAXBException, IOException {
        return xmlMapper.writeValueAsString(obj);
    }

    /**
     * 53      * xml转对象
     * 54      *
     * 55      * @throws JAXBException
     * 56
     */
    public static Object unMarshal(Class<?> cl, String xmlStr) throws JAXBException, IOException {
        return xmlMapper.readValue(xmlStr, cl);
    }


    @SuppressWarnings("rawtypes")
    public static void mapToXml(Map map, StringBuffer sb) {
        Set set = map.keySet();
        for (Iterator it = set.iterator(); it.hasNext(); ) {
            String key = (String) it.next();
            Object value = map.get(key);
            if (null == value)
                value = "";
            if (value instanceof List) {
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<" + key + ">");
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i) instanceof HashMap) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXml(hm, sb);
                    } else {
                        sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                    }
                }
                sb.append("</" + key + ">");

            } else {
                if (value instanceof HashMap) {
                    sb.append("<" + key + ">");
                    mapToXml((HashMap) value, sb);
                    sb.append("</" + key + ">");
                } else {
                    sb.append("<" + key + ">" + value + "</" + key + ">");
                }

            }

        }
    }

    @SuppressWarnings("rawtypes")
    public static String mapToXml(Map map) {
        StringBuffer sb = new StringBuffer();
        Set set = map.keySet();
        sb.append("<body>");
        for (Iterator it = set.iterator(); it.hasNext(); ) {
            String key = (String) it.next();
            Object value = map.get(key);
            if (null == value)
                value = "";
            if (value instanceof List) {
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<" + key + ">");
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i) instanceof HashMap) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXml(hm, sb);
                    } else {
                        sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                    }
                }
                sb.append("</" + key + ">");

            } else {
                if (value instanceof HashMap) {
                    sb.append("<" + key + ">");
                    mapToXml((HashMap) value, sb);
                    sb.append("</" + key + ">");
                } else {
                    sb.append("<" + key + ">" + value + "</" + key + ">");
                }

            }
        }
        sb.append("</body>");
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String listMapToXml(List<Map<String, Object>> map) {
        StringBuffer sb = new StringBuffer();
        sb.append("<body><RowSet>\n" +
                "      <Rows>");
        for (int i = 0; i < map.size(); i++) {
            Set set = map.get(i).keySet();
            for (Iterator it = set.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                Object value = map.get(i).get(key);
                if (null == value)
                    value = "";
                if (value instanceof List) {
                    ArrayList list = (ArrayList) map.get(i).get(key);
                    sb.append("<" + key + ">");
                    for (int j = 0; j < list.size(); j++) {
                        if (list.get(j) instanceof HashMap) {
                            HashMap hm = (HashMap) list.get(j);
                            mapToXml(hm, sb);
                        } else {
                            sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                        }
                    }
                    sb.append("</" + key + ">");
                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + ">");
                        mapToXml((HashMap) value, sb);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }
            }
        }
        sb.append(" </Rows>\n" +
                "    </RowSet></body>");
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String oldMapToXml(Map map) {
        StringBuffer sb = new StringBuffer();
        Set set = map.keySet();
        sb.append("<RowSet>\n" +
                "\t<Row>");
        for (Iterator it = set.iterator(); it.hasNext(); ) {
            String key = (String) it.next();
            Object value = map.get(key);
            if (null == value)
                value = "";
            if (value instanceof List) {
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<" + key + ">");
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i) instanceof HashMap) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXml(hm, sb);
                    } else {
                        sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                    }
                }
                sb.append("</" + key + ">");

            } else {
                if (value instanceof HashMap) {
                    sb.append("<" + key + ">");
                    mapToXml((HashMap) value, sb);
                    sb.append("</" + key + ">");
                } else {
                    sb.append("<" + key + ">" + value + "</" + key + ">");
                }

            }
        }
        sb.append("</Row>\n" +
                "</RowSet>");
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String LBMapToXml(Map map) {
        StringBuffer sb = new StringBuffer();
        Set set = map.keySet();
        sb.append("<ROWSET>\n" +
                "\t<ROWS>");
        for (Iterator it = set.iterator(); it.hasNext(); ) {
            String key = (String) it.next();
            Object value = map.get(key);
            if (null == value)
                value = "";
            if (value instanceof List) {
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<" + key + ">");
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i) instanceof HashMap) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXml(hm, sb);
                    } else {
                        sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                    }
                }
                sb.append("</" + key + ">");

            } else {
                if (value instanceof HashMap) {
                    sb.append("<" + key + ">");
                    mapToXml((HashMap) value, sb);
                    sb.append("</" + key + ">");
                } else {
                    sb.append("<" + key + ">" + value + "</" + key + ">");
                }

            }
        }
        sb.append("</ROWS>\n" +
                "</ROWSET>");
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String LBMapToXml(List<Map<String, Object>> map) {
        StringBuffer sb = new StringBuffer();
        sb.append("<ROWSET>\n" +
                "\t<ROWS>");
        for (int i = 0; i < map.size(); i++) {
            Set set = map.get(i).keySet();
            for (Iterator it = set.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                Object value = map.get(i).get(key);
                if (null == value)
                    value = "";
                if (value instanceof List) {
                    ArrayList list = (ArrayList) map.get(i).get(key);
                    sb.append("<" + key + ">");
                    for (int j = 0; j < list.size(); j++) {
                        if (list.get(j) instanceof HashMap) {
                            HashMap hm = (HashMap) list.get(j);
                            mapToXml(hm, sb);
                        } else {
                            sb.append("<" + key + ">" + list.get(i) + "</" + key + ">");
                        }
                    }
                    sb.append("</" + key + ">");

                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + ">");
                        mapToXml((HashMap) value, sb);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + ">" + value + "</" + key + ">");
                    }
                }
            }
        }
        sb.append("</ROWS>\n" +
                "</ROWSET>");
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static Map<String, Object> xml2Map(String in) throws DocumentException {
        Document doc = DocumentHelper.parseText(in);
        Map<String, Object> map = new HashMap<String, Object>();
        if (doc == null)
            return map;
        Element root = doc.getRootElement();
        for (Iterator iterator = root.elementIterator(); iterator.hasNext(); ) {
            Element e = (Element) iterator.next();
            // System.out.println(e.getName());
            List list = e.elements();
            if (list.size() > 0) {
                map.put(e.getName(), Dom2Map(e));
            } else
                map.put(e.getName(), e.getText());
        }
        return map;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public static Map Dom2Map(Element e) {
        Map map = new HashMap();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();

                if (iter.elements().size() > 0) {
                    Map m = Dom2Map(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), m);
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(iter.getText());
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(iter.getText());
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), iter.getText());
                }
            }
        } else
            map.put(e.getName(), e.getText());
        return map;
    }
}
